<?php

namespace App\Http\Controllers\Api\App;

use Carbon\Carbon;
use App\Models\User;
use App\Models\Level;
use App\Services\Token;
use App\Utils\FundType;
use App\Models\Recharge;
use App\Models\UserFund;
use App\Models\Withdraw;
use App\Models\BankAccount;
use Illuminate\Http\Request;
use App\Models\AlipayAccount;
use App\Utils\TransferStatus;
use App\Models\AmountTransfer;
use App\Models\ReceiptAccount;
use Illuminate\Support\Facades\DB;
use Tymon\JWTAuth\Facades\JWTAuth;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use App\Http\Requests\App\UserRequest;

class UserController extends Controller
{
    public function login(Request $request)
    {
        $credentials = request(['username', 'password']);
        $token = User::login($credentials);
        if (!$token) {
            return error('账号或密码错误');
        }
        if(Auth::guard('user')->user()['status'] == -1) {
            return error('账号异常');
        }
        return $this->respondWithToken($token);
    }

    /**
     * 注册
     *
     * @return \Illuminate\Http\Response
     */
    public function register(UserRequest $request)
    {
        DB::beginTransaction();
        try {
            $data = [];
            if (Cache::get('verify_code' . $request->username) != $request->verify_code) {
                return errorMsg('验证码错误！');
            }
            $user = User::where('id', $request->invite_code)->first();
            if (isset($user)) {
                $data['invite_id'] = $user->id;
            } else {
                return errorMsg('邀请码不正确！');
            }
            //TODO: 必须是手机号码,验证手机号码格式
            $data['username'] = $request->username;
            $data['password'] = bcrypt($request->password);
            // $data['invite_code'] = str_random(8);
            $data['nickname'] = $request->nickname ?? str_random(8);
            $data['add_type'] = 1;
            $data['level_id'] = Level::getLevels()[0]['id'];
            $newUser = User::create($data);
            if ($newUser) {
                DB::commit();
                return success('注册成功');
            }
        } catch (\Exception $e) {
            DB::rollback();
            return error($e->getMessage());
        }
    }

    public function forgetPassword(Request $request)
    {
        DB::beginTransaction();
        try {
            // dd($request->verify_code);
            if (Cache::get('verify_code' . $request->username) != $request->verify_code) {
                return errorMsg('验证码错误！');
            }
            $user = User::where('username', $request->username)->first();
            if (!isset($user)) {
                return errorMsg('用户不存在！');
            }
            $user->password = bcrypt($request->password);
            if ($user->save()) {
                DB::commit();
                return success();
            }
        } catch (\Exception $e) {
            DB::rollback();
            return error($e->getMessage());
        }
    }

    public function user(Request $request)
    {
        $user = User::find($request->user_id, ['id', 'nickname', 'username', 'avatar']);
        return success($user);
    }

    public function logout()
    {
        if (Auth::guard('user')->check()) {
            Auth::guard('user')->logout();
        }
        return success([], '登出成功');
    }

    protected function respondWithToken($token)
    {
        $user = User::with('level:id,name', 'alipay', 'bank')->find(Auth::guard('user')->id());
        return response()->json([
            'access_token' => $token,
            'token_type' => 'Bearer',
            'expires_in' => JWTAuth::factory()->getTTL() * 60,
            'user' => $user,
            'status' => 'success'
        ]);
    }

    /**
     * 获取用户信息
     *
     * @return void
     */
    public function info()
    {
        $user = User::with('level:id,name', 'alipay', 'bank')->find(Token::id());
        $user->today_income = UserFund::where('type', FundType::ROBOT_INCOME)->whereDate('created_at', date('Y-m-d'))->where('user_id', Token::id())->sum('change_amount');
        $reward = UserFund::where('type', FundType::INVITE_INCOME)->whereDate('created_at', date('Y-m-d'))->where('user_id', Token::id())->sum('change_amount');
        $user->today_income += $reward;
        $user->today_income = number_format($user->today_income, 2);
        $user->amount_total = number_format($user->amount_total, 2);
        Level::isUpgrade(Token::id());
        return success($user);
    }

    /**
     * 用户提现
     *
     * @return void
     */
    public function withdraw(Request $request)
    {
        $timeFlag = date('H') >= 18 || date('H') < 10;
        if ((0 == Carbon::now()->dayOfWeek || Carbon::now()->dayOfWeek == 6) || $timeFlag) {
            return error('提现时间为周一到周五的10点到18点');
        }
        $price = $request->price;
        $type = $request->type;
        if ($price < 10) {
            return error('最低提现10元');
        }
        if ($price % 10 != 0) {
            return error('提现金额必须是10的倍数');
        }
        //计算手续费
        // $fee = 2;
        // if (($price * 0.05) > 2) {
        //     $fee = $price * 0.05;
        // }
        $fee = $price * 0.05;
        $priceTotal = $price + $fee;
        DB::beginTransaction();
        try {
            $withdrawCount =  Withdraw::lockForUpdate()->where('user_id', Token::id())->whereDate('created_at', date('Y-m-d'))->count();
            if ($withdrawCount > 0) {
                return errorMsg('一天只限提现1次，请明天再来');
            }
            $user = User::lockForUpdate()->find(Token::id(), ['id', 'amount', 'alipay_account_id', 'bank_account_id', 'openid']);
            if (!isset($user)) {
                return errorMsg('用户不存在');
            }
            if ($user->alipay_account_id == 0) {
                return errorMsg('请先绑定支付宝');
            }
            if ($user->bank_account_id == 0) {
                return errorMsg('请先绑定银行卡');
            }
            if (!$user->openid) {
                return errorMsg('请先绑定微信');
            }
            if ($priceTotal > $user->amount) {
                return errorMsg('余额不足');
            }
            $user->decrement('amount', $priceTotal);
            // $accountId = $type == 0 ? $user->alipay_account_id : $user->bank_account_id;
            Withdraw::create([
                'price' => $price,
                'handle_fee' => $fee,
                'user_id' => $user->id,
                'type' => $type,
                'account_id' => $user->alipay_account_id,
                'order_no' => getOrderNo()
            ]);
            UserFund::create([
                'user_id' => $user->id,
                'type' => FundType::WITHDRAW,
                'change_amount' => -$priceTotal,
                'after_amount' => $user->amount,
                'content' => '用户提现' . $price . '元，手续费' . $fee . '元',
                'remark' => '提现发起'
            ]);
            DB::commit();
            return success();
        } catch (\Exception $e) {
            DB::rollback();
            return error($e->getMessage());
        }
    }

    /**
     * 用户资金记录
     */
    public function fund(Request $request)
    {
        $type = $request->type;
        $funds = UserFund::when($type > -1, function ($query) use ($type) {
            return $query->where('type', $type);
        })->where('user_id', Token::id())->orderBy('id', 'desc')->paginate(config('common.pagesize'));
        return success($funds);
    }

    /**
     * 修改密码
     *
     * @param Request $request
     * @return void
     */
    public function editPassword(Request $request)
    {
        $user = User::find(Token::id());
        if (!isset($user)) {
            return error('用户不存在');
        }
        $credentials = [
            'username' => $user->username,
            'password' => $request->old_password
        ];
        $token = User::login($credentials);
        if (!$token) {
            return error('原密码错误');
        }
        if ($request->old_password == $request->new_password) {
            return error('新密码不能跟原密码相同');
        }
        $user->password = bcrypt($request->new_password);
        if ($user->save()) {
            return success();
        }
        return error();
    }

    /**
     * 编辑个人信息
     */
    public function editInfo(Request $request)
    {
        $user = User::with('level:id,name', 'alipay', 'bank')->find(Token::id());
        if (!isset($user)) {
            return error('用户不存在');
        }
        if (!preg_match('/^[A-Za-z0-9_\x{4e00}-\x{9fa5}]+$/u', $request->nickname)) {
            return error('用户名由2-16位数字或字母、汉字、下划线组成！');
        }
        $user->nickname = $request->nickname;
        $user->wechat = $request->wechat;
        $user->phone = $request->phone;
        // $user->avatar = $request->avatar;
        if ($user->save()) {
            return success($user);
        }
        return error();
    }

    public function bindAlipay(Request $request)
    {
        $user = User::find(Token::id());
        if (!isset($user)) {
            return error('用户不存在');
        }
        if ($user->alipay_account_id == 0) {
            $account = AlipayAccount::create([
                'user_id' => $user->id,
                'name' => $request->name,
                'account' => $request->account,
            ]);
            $user->alipay_account_id = $account->id;
        } else {
            if (Cache::get('verify_code' . $user->username) != $request->code) {
                return error('验证码错误！');
            }
            AlipayAccount::find($user->alipay_account_id)->update([
                'name' => $request->name,
                'account' => $request->account,
            ]);
        }
        if ($user->save()) {
            $user = User::with('level:id,name', 'alipay', 'bank')->find(Token::id());
            return success($user);
        }
        return error();
    }

    public function bindBank(Request $request)
    {
        $user = User::find(Token::id());
        if (!isset($user)) {
            return error('用户不存在');
        }
        if ($user->bank_account_id == 0) {
            $account = BankAccount::create([
                'user_id' => $user->id,
                'bank' => $request->bank,
                'name' => $request->name,
                'account' => $request->account,
            ]);
            $user->bank_account_id = $account->id;
        } else {
            if (Cache::get('verify_code' . $user->username) != $request->code) {
                return error('验证码错误！');
            }
            BankAccount::find($user->bank_account_id)->update([
                'bank' => $request->bank,
                'name' => $request->name,
                'account' => $request->account,
            ]);
        }
        if ($user->save()) {
            $user = User::with('level:id,name', 'alipay', 'bank')->find(Token::id());
            return success($user);
        }
        return error();
    }

    public function bindWechat(Request $request)
    {
        $user = User::find(Token::id());
        if (!isset($user)) {
            return error('用户不存在');
        }
        $token = str_random();
        Cache::put($token, Token::id(), 300);
        if ($user->openid) {
            if (Cache::get('verify_code' . $user->username) != $request->code) {
                return error('验证码错误！');
            }
        }
        $host = file_get_contents('http://47.104.70.65/api/api/host');
        $url = $host . '/api/api/getOpenid?redirect_uri=' . 'https://car-api.hyuta.com/bind-wechat?token=' . $token;
        return success($url);
    }


    public function getReceiptAccount()
    {
        $account = ReceiptAccount::first();
        return success($account);
    }

    public function recharge(Request $request)
    {
        $data = $request->all();
        $data['user_id'] = Token::id();
        $data['order_no'] = getOrderNo();
        if($data['price'] < 10) {
            return error('最低充值10元');
        }
        DB::beginTransaction();
        try {
            $record = Recharge::lockForUpdate()->where('user_id', $data['user_id'])->where('verify_status', 0)->first();
            if (isset($record)) {
                return errorMsg('您有充值正在审核，请等待审核完成');
            }
            $recharge = Recharge::create($data);
            if (isset($recharge)) {
                $user = User::find($recharge->user_id);
                UserFund::create([
                    'user_id' => $user->id,
                    'type' => FundType::RECHARGE,
                    'change_amount' => 0,
                    'after_amount' => $user->amount,
                    'content' =>  '提交充值申请，充值' . $recharge->price . '元,请等待审核',
                    'remark' => '充值申请'
                ]);
                DB::commit();
                return success();
            }
        } catch (\Exception $e) {
            DB::rollback();
            return error($e->getMessage());
        }
    }

    public function getLastTransfer(Request $request)
    {
        $userId = Token::id();
        $transfer = AmountTransfer::where('from_user_id', $userId)->orWhere('to_user_id', $userId)->orderBy('id', 'desc')->first();
        return success($transfer);
    }

    public function getTransfer(Request $request)
    {
        $userId = Token::id();
        $transfer = AmountTransfer::with(['fromUser.alipay', 'toUser:id,nickname'])->where('from_user_id', $userId)->orWhere('to_user_id', $userId)->orderBy('id', 'desc')->first();
        // if (isset($transfer)) {
        //     if (!in_array($transfer->status, [TransferStatus::DOING, TransferStatus::AGREE])) {
        //         $transfer = [];
        //     }
        // }
        return success($transfer);
    }

    public function refuseTransfer(Request $request)
    {
        DB::beginTransaction();
        try {
            $transfer =  AmountTransfer::lockForUpdate()->find($request->id);
            if ($transfer->status != TransferStatus::DOING) {
                return errorMsg('交易状态错误');
            }
            $user = User::find($transfer->from_user_id);
            $priceTotal = $transfer->price + $transfer->handle_fee;
            $user->increment('amount', $priceTotal);
            UserFund::create([
                'user_id' => $user->id,
                'type' => FundType::TRANSFER,
                'change_amount' => $priceTotal,
                'after_amount' => $user->amount,
                'content' => '接收人拒绝转让交易，退回金额' . $transfer->price . '元和手续费' . $transfer->handle_fee . '元',
                'remark' => '转让订单'
            ]);
            $transfer->status = TransferStatus::REFUSE;
            $transfer->save();
            DB::commit($transfer);
            return success();
        } catch (\Exception $e) {
            DB::rollback();
            return error($e->getMessage());
        }
    }

    public function agreeTransfer(Request $request)
    {
        $transfer =  AmountTransfer::find($request->id);
        if ($transfer->status != TransferStatus::DOING) {
            return error('交易状态错误');
        }
        $transfer->status = TransferStatus::AGREE;
        // $transfer->image = $request->image;
        $transfer->save();
        $transfer->load(['fromUser.alipay', 'toUser:id,nickname']);
        return success($transfer);
    }

    public function uploadImageTransfer(Request $request)
    {
        $transfer =  AmountTransfer::find($request->id);
        if ($transfer->status != TransferStatus::AGREE) {
            return error('交易状态错误');
        }
        $transfer->status = TransferStatus::UPLOAD_IMAGE;
        $transfer->image = $request->image;
        $transfer->save();
        $transfer->load(['fromUser.alipay', 'toUser:id,nickname']);
        return success($transfer);
    }

    public function cancelTransfer(Request $request)
    {
        DB::beginTransaction();
        try {
            $transfer =  AmountTransfer::lockForUpdate()->find($request->id);
            if ($transfer->status != TransferStatus::DOING) {
                return errorMsg('交易状态错误,请重进页面');
            }
            $user = User::find($transfer->from_user_id);
            $priceTotal = $transfer->price + $transfer->handle_fee;
            $user->increment('amount', $priceTotal);
            UserFund::create([
                'user_id' => $user->id,
                'type' => FundType::TRANSFER,
                'change_amount' => $priceTotal,
                'after_amount' => $user->amount,
                'content' => '取消转让交易，退回金额' . $transfer->price . '元和手续费' . $transfer->handle_fee . '元',
                'remark' => '转让订单'
            ]);
            $transfer->status = TransferStatus::CANCEL;
            $transfer->save();
            DB::commit($transfer);
            return success();
        } catch (\Exception $e) {
            DB::rollback();
            return error($e->getMessage());
        }
    }

    public function confirmTransfer(Request $request)
    {

        DB::beginTransaction();
        try {
            $transfer =  AmountTransfer::lockForUpdate()->find($request->id);
            if (!$transfer->image) {
                return errorMsg('上传凭证为空，不能确认');
            }
            if ($transfer->status != TransferStatus::UPLOAD_IMAGE) {
                return errorMsg('交易状态错误');
            }
            $fromUser = User::find($transfer->from_user_id);
            UserFund::create([
                'user_id' => $fromUser->id,
                'type' => FundType::TRANSFER,
                'change_amount' => 0,
                'after_amount' => $fromUser->amount,
                'content' => '完成转让交易',
                'remark' => '转让订单'
            ]);
            $toUser = User::find($transfer->to_user_id);
            $toUser->increment('amount', $transfer->price);
            UserFund::create([
                'user_id' => $toUser->id,
                'type' => FundType::TRANSFER,
                'change_amount' => $transfer->price,
                'after_amount' => $toUser->amount,
                'content' => '完成转让交易,获得余额' . $transfer->price . '元',
                'remark' => '转让订单'
            ]);
            $transfer->status = TransferStatus::FINISH;
            $transfer->save();
            DB::commit();
            return success($transfer);
        } catch (\Exception $e) {
            DB::rollback();
            return error($e->getMessage());
        }
    }

    public function transfer(Request $request)
    {
        $user = $request->user;
        $price = $request->price;
        $fromUserId = Token::id();
        if ($user == $fromUserId) {
            return error('不能转让给自己');
        }
        if ($price < 10) {
            return error('转让金额最小为10');
        }
        if ($price % 10 == 0) {
            return error('转让金额必须为10的倍数');
        }
        $toUser = User::where('id', $user)->orWhere('username', $user)->first(['id']);
        if (!isset($toUser)) {
            return error('请确认接收用户的ID或用户名');
        }
        $formUser = User::find($fromUserId, ['id', 'amount', 'alipay_account_id']);

        if ($formUser->alipay_account_id == 0) {
            return error('请先绑定支付宝');
        }
        $handleFee = $price * 0.025;
        $priceTotal = $price + $handleFee;
        if ($formUser->amount < $priceTotal) {
            return error('余额不足');
        }
        DB::beginTransaction();
        try {
            $transfer = AmountTransfer::lockForUpdate()->where('from_user_id', $fromUserId)->orWhere('to_user_id', $fromUserId)->orderBy('id', 'desc')->first();
            if (isset($transfer) && in_array($transfer->status, [0, 1])) {
                return errorMsg('您有订单正在转让，请完成后再试');
            }
            $amountTransfer = AmountTransfer::create([
                'order_no' => getOrderNo(),
                'from_user_id' => $fromUserId,
                'to_user_id' => $toUser->id,
                'price' => $price,
                'handle_fee' => $handleFee,
                'status' => TransferStatus::DOING
            ]);
            $amountTransfer->load(['fromUser.alipay', 'toUser:id,nickname']);
            $formUser->decrement('amount', $priceTotal);
            UserFund::create([
                'user_id' => $formUser->id,
                'type' => FundType::TRANSFER,
                'change_amount' => -$priceTotal,
                'after_amount' => $formUser->amount,
                'content' => '发起转让，转让' . $price . '元，手续费' . $handleFee . '元',
                'remark' => '转让订单'
            ]);
            DB::commit();
            return success($amountTransfer);
        } catch (\Exception $e) {
            DB::rollback();
            return error($e->getMessage());
        }
    }
}
